'''
Created on 18.10.2011

@author: hkh
'''
'''
Created on 16.10.2011

@author: hkh
'''
from numpy import *
from scipy import *
from datetime import *
from TimeUtils import *

class CpiEntity(object):
    '''
    CpiEntity implements a CPI value that consists of the CPI measure and
    the relevant date
    Parameters: 
        cpidate:        reference date for CPI value
        cpivalue:       CPI value
    Returns:
    '''
    def __init__(self, cpidate, cpivalue):
        self.cpidate    = cpidate
        self.cpivalue   = cpivalue

class CpiCurve(object):
    cpicurve = []
    def __init__(self):
        self.cpicurve.append(CpiEntity(date(2004,9,1), 235.7))
        self.cpicurve.append(CpiEntity(date(2004,10,1), 234.6))
        self.cpicurve.append(CpiEntity(date(2004,11,1), 234.6))
        self.cpicurve.append(CpiEntity(date(2004,12,1), 235.6))
        self.cpicurve.append(CpiEntity(date(2005,1,1), 237.4))
        self.cpicurve.append(CpiEntity(date(2005,2,1), 237.9))
        self.cpicurve.append(CpiEntity(date(2005,3,1), 239.0))
        self.cpicurve.append(CpiEntity(date(2005,4,1), 239.2))
        self.cpicurve.append(CpiEntity(date(2005,5,1), 239.7))
        self.cpicurve.append(CpiEntity(date(2005,6,1), 241.5))
        self.cpicurve.append(CpiEntity(date(2005,7,1), 242.0))
        self.cpicurve.append(CpiEntity(date(2005,8,1), 240.7))
        self.cpicurve.append(CpiEntity(date(2005,9,1), 242.7))
        self.cpicurve.append(CpiEntity(date(2005,10,1), 243.2))
        self.cpicurve.append(CpiEntity(date(2005,11,1), 246.9))
        self.cpicurve.append(CpiEntity(date(2005,12,1), 248.4))
        self.cpicurve.append(CpiEntity(date(2006,1,1), 248.0))
        self.cpicurve.append(CpiEntity(date(2006,2,1), 248.9))
        self.cpicurve.append(CpiEntity(date(2006,3,1), 249.7))
        self.cpicurve.append(CpiEntity(date(2006,4,1), 249.5))
        self.cpicurve.append(CpiEntity(date(2006,5,1), 252.3))
        self.cpicurve.append(CpiEntity(date(2006,6,1), 255.2))
        self.cpicurve.append(CpiEntity(date(2006,7,1), 258.9))
        self.cpicurve.append(CpiEntity(date(2006,8,1), 261.9))
        self.cpicurve.append(CpiEntity(date(2006,9,1), 263.1))
        self.cpicurve.append(CpiEntity(date(2006,10,1), 264.0))
        self.cpicurve.append(CpiEntity(date(2006,11,1), 265.6))
        self.cpicurve.append(CpiEntity(date(2006,12,1), 266.2))
        self.cpicurve.append(CpiEntity(date(2007,1,1), 266.1))
        self.cpicurve.append(CpiEntity(date(2007,2,1), 266.2))
        self.cpicurve.append(CpiEntity(date(2007,3,1), 266.9))
        self.cpicurve.append(CpiEntity(date(2007,4,1), 268.0))
        self.cpicurve.append(CpiEntity(date(2007,5,1), 267.1))
        self.cpicurve.append(CpiEntity(date(2007,6,1), 268.7))
        self.cpicurve.append(CpiEntity(date(2007,7,1), 271.0))
        self.cpicurve.append(CpiEntity(date(2007,8,1), 272.4))
        self.cpicurve.append(CpiEntity(date(2007,9,1), 273.0))
        self.cpicurve.append(CpiEntity(date(2007,10,1), 273.1))
        self.cpicurve.append(CpiEntity(date(2007,11,1), 276.7))
        self.cpicurve.append(CpiEntity(date(2007,12,1), 278.1))
        self.cpicurve.append(CpiEntity(date(2008,1,1), 279.9))
        self.cpicurve.append(CpiEntity(date(2008,2,1), 281.8))
        self.cpicurve.append(CpiEntity(date(2008,3,1), 282.3))
        self.cpicurve.append(CpiEntity(date(2008,4,1), 286.2))
        self.cpicurve.append(CpiEntity(date(2008,5,1), 290.4))
        self.cpicurve.append(CpiEntity(date(2008,6,1), 300.3))
        self.cpicurve.append(CpiEntity(date(2008,7,1), 304.4))
        self.cpicurve.append(CpiEntity(date(2008,8,1), 307.1))
        self.cpicurve.append(CpiEntity(date(2008,9,1), 310.0))
        self.cpicurve.append(CpiEntity(date(2008,10,1), 312.8))
        self.cpicurve.append(CpiEntity(date(2008,11,1), 315.5))
        self.cpicurve.append(CpiEntity(date(2008,12,1), 322.3))
        self.cpicurve.append(CpiEntity(date(2009,1,1), 327.9))
        self.cpicurve.append(CpiEntity(date(2009,2,1), 332.9))
        self.cpicurve.append(CpiEntity(date(2009,3,1), 334.8))
        self.cpicurve.append(CpiEntity(date(2009,4,1), 336.5))
        self.cpicurve.append(CpiEntity(date(2009,5,1), 334.5))
        self.cpicurve.append(CpiEntity(date(2009,6,1), 336.0))
        self.cpicurve.append(CpiEntity(date(2009,7,1), 339.8))
        self.cpicurve.append(CpiEntity(date(2009,8,1), 344.5))
        self.cpicurve.append(CpiEntity(date(2009,9,1), 345.1))
        self.cpicurve.append(CpiEntity(date(2009,10,1), 346.9))
        self.cpicurve.append(CpiEntity(date(2009,11,1), 349.6))
        self.cpicurve.append(CpiEntity(date(2009,12,1), 353.6))
        self.cpicurve.append(CpiEntity(date(2010,1,1), 356.2))
        self.cpicurve.append(CpiEntity(date(2010,2,1), 357.9))
        self.cpicurve.append(CpiEntity(date(2010,3,1), 356.8))
        self.cpicurve.append(CpiEntity(date(2010,4,1), 360.9))
        self.cpicurve.append(CpiEntity(date(2010,5,1), 362.9))
        self.cpicurve.append(CpiEntity(date(2010,6,1), 363.8))
        self.cpicurve.append(CpiEntity(date(2010,7,1), 365.3))
        self.cpicurve.append(CpiEntity(date(2010,8,1), 364.1))
        self.cpicurve.append(CpiEntity(date(2010,9,1), 361.7))
        self.cpicurve.append(CpiEntity(date(2010,10,1), 362.6))
        self.cpicurve.append(CpiEntity(date(2010,11,1), 362.6))
        self.cpicurve.append(CpiEntity(date(2010,12,1), 365.3))
        self.cpicurve.append(CpiEntity(date(2011,1,1), 365.5))
        self.cpicurve.append(CpiEntity(date(2011,2,1), 366.7))
        self.cpicurve.append(CpiEntity(date(2011,3,1), 363.4))
        self.cpicurve.append(CpiEntity(date(2011,4,1), 367.7))
        self.cpicurve.append(CpiEntity(date(2011,5,1), 371.2))
        self.cpicurve.append(CpiEntity(date(2011,6,1), 374.1))
        self.cpicurve.append(CpiEntity(date(2011,7,1), 377.6))
        self.cpicurve.append(CpiEntity(date(2011,8,1), 379.5))
        self.cpicurve.append(CpiEntity(date(2011,9,1), 379.9))
        self.cpicurve.append(CpiEntity(date(2011,10,1), 380.9))
        self.cpicurve.append(CpiEntity(date(2011,11,1), 383.3))
        self.cpicurve.append(CpiEntity(date(2011,12,1), 384.6))
        self.cpicurve.append(CpiEntity(date(2012,1,1), 384.6))
        self.cpicurve.append(CpiEntity(date(2012,2,1), 386.0))
        self.cpicurve.append(CpiEntity(date(2012,3,1), 387.1))
        self.cpicurve.append(CpiEntity(date(2012,4,1), 391.0))
        self.cpicurve.append(CpiEntity(date(2012,5,1), 395.1))
        self.cpicurve.append(CpiEntity(date(2012,6,1), 398.2))
        '''
        self.cpicurve.append(CpiEntity(date(2012,7,1), 399.8))
        self.cpicurve.append(CpiEntity(date(2012,8,1), 401.0))
        self.cpicurve.append(CpiEntity(date(2012,9,1), 399.0))
        '''
        self.cpicurve.append(CpiEntity(date(2012,7,1), 398.1))
        self.cpicurve.append(CpiEntity(date(2012,8,1), 400.1))
        self.cpicurve.append(CpiEntity(date(2012,9,1), 397.2))
        self.cpicurve.append(CpiEntity(date(2012,10,1), 396.6))
        self.cpicurve.append(CpiEntity(date(2012,11,1), 399.6))
        self.cpicurve.append(CpiEntity(date(2012,12,1), 400.7))
        self.cpicurve.append(CpiEntity(date(2013,1,1), 402.0))
    def dailycpi(self, settlementdate):
        startdate = date(2004,9,1)

        startindex = self.__findindex(settlementdate)
        endindex = startindex + 1
      
        '''
        Cast exception here !! Also if endindex doesn't exist, we are not Nostradamus
        '''
        if settlementdate < startdate:
            print 'We dont remember past 1st of September 2004, sorry.'

        daysinmonth = self.cpicurve[endindex].cpidate.toordinal() \
                      - self.cpicurve[startindex].cpidate.toordinal()

        cpi1 = self.cpicurve[startindex].cpivalue
        cpi2 = self.cpicurve[endindex].cpivalue

        settlementday = settlementdate.day

        dcpi = cpi1+((settlementday - 1.0)/daysinmonth * (cpi2 - cpi1))

        return dcpi

    def dailycpihff(self, settlementdate):
        startdate = date(2004,9,1)

        startindex = self.__findindex(settlementdate)
        endindex = startindex + 1
      
        '''
        Cast exception here !! Also if endindex doesn't exist, we are not Nostradamus
        '''
        if settlementdate < startdate:
            print 'We dont remember past 1st of September 2004, sorry.'

        daysinmonth = self.cpicurve[endindex].cpidate.toordinal() \
                      - self.cpicurve[startindex].cpidate.toordinal()

        cpi1 = self.cpicurve[startindex].cpivalue
        cpi2 = self.cpicurve[endindex].cpivalue

        settlementday = settlementdate.day
        if settlementday > 30:
            settlementday = 30
        dcpi = cpi1 * (cpi2 / cpi1)**((settlementday - 1.0)/30.0)

        return dcpi
        
    def __findindex(self, settlementdate):
        indexlength = len(self.cpicurve)

        'The dates for the CPI are the first days of each month'
        refdate = date(settlementdate.year, settlementdate.month, 1)

        index = 0
        for item in self.cpicurve:
            if refdate == item.cpidate:
                return index
            index += 1
